package com.example.xcService.pojo.channels.impl;

import com.alibaba.fastjson.JSONObject;
import com.example.xcService.pojo.channels.ChannelResult;
import com.example.xcService.pojo.channels.ChannelService;
import com.example.xcService.pojo.tool.HttpTool;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import java.io.UnsupportedEncodingException;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Pattern;

/*
* 合合（扫描王）
* */
@Slf4j
public class Plugin_ECARD_P041 implements ChannelService {

    @Override
    public ChannelResult QueryBalance(JSONObject apiConfig) {
        System.out.println("成功调用了QueryBalance");
        return  ChannelResult.success("success");
    }

    @Override
    public ChannelResult Submit(JSONObject apiConfig, Map<String, Object> data) {

        try {
            String appId = apiConfig.getString("AppId");
            String cooperateNo = apiConfig.getString("CooperateNo");
            String key = apiConfig.getString("AppKey");
            String publicKey = apiConfig.getString("PublicKey");
            String submitUrl = apiConfig.getString("SubmitUrl");

            long timestamp = System.currentTimeMillis();
            String accountVal = String.valueOf(data.get("AccountVal"));
            String channelOrderCode = String.valueOf(data.get("ChannelOrderCode"));
            String supProductId = String.valueOf(data.get("SUPProductId"));

            String encryptedAccount = encryptByPublicKey(accountVal.getBytes(), publicKey);

            HashMap<String, String> submitParams = new HashMap<>();
            submitParams.put("app_id",appId); //应⽤ID
            submitParams.put("cooperate_no",cooperateNo);//合作号
            submitParams.put("timestamp",String.valueOf(timestamp));//请求时间戳ms，算在计算签名内
            //submitParams.put("account",accountVal);//仅沙盒环境可⽤，仅联调时使⽤
            submitParams.put("account_encrypt",encryptedAccount);//正式环境必须通过RSA加密，公钥扫描全能王提供 加密账号
            if (Pattern.matches("^1[3456789]\\d{9}$", accountVal) == true) {
                submitParams.put("area_code","86");// 如果account、 account_encrypt是⼿机号必传  eg: 86 :中国
            }
            submitParams.put("order_id",channelOrderCode);
            submitParams.put("product_id",supProductId);//购买项
            String sign = generateSign(submitParams, key);
            submitParams.put("sign",sign);

            String resStr = HttpTool.sendPost(submitUrl, submitParams);
            JSONObject resObj = JSONObject.parseObject(resStr);
            String code = resObj.getString("code");
            String msg = resObj.getString("msg");
            if (code.equals("0")||code.equals("10040105")||code.equals("10040106")||code.equals("10040112")){
                return ChannelResult.IN_PROCESS("充值中");
            }
            if (code.equals("10040002") ||code.equals("10040108")){
                return ChannelResult.error(msg);
            }
            return ChannelResult.FAILED(msg);
        }catch (Exception e) {
            e.printStackTrace();
            log.error("合合扫描王提交订单接口错误：",e);
            return  ChannelResult.error("合合扫描王提交订单接口错误");
        }

    }

    @Override
    public ChannelResult Query(JSONObject apiConfig, Map<String, Object> data) {
        try {
            String appId = apiConfig.getString("AppId");
            String cooperateNo = apiConfig.getString("CooperateNo");
            String key = apiConfig.getString("AppKey");
            String queryUrl = apiConfig.getString("QueryUrl");

            long timestamp = System.currentTimeMillis();
            HashMap<String, String> queryParams = new HashMap<>();
            queryParams.put("app_id",appId);
            queryParams.put("cooperate_no",cooperateNo);
            queryParams.put("timestamp",String.valueOf(timestamp));
            queryParams.put("order_id",String.valueOf(data.get("ChannelOrderCode")));

            String sign = generateSign(queryParams, key);
            queryParams.put("sign",sign);

            String resStr = HttpTool.sendPost(queryUrl, queryParams);
            JSONObject resObj = JSONObject.parseObject(resStr);
            String code = resObj.getString("code");
            String msg = resObj.getString("msg");
            if (code.equals("0")){
                String resData = resObj.getString("data");
                JSONObject parseObject = JSONObject.parseObject(resData);
                String status = parseObject.getString("status");
                if (status.equals("0")){
                    return ChannelResult.IN_PROCESS("充值中");
                }
                if (status.equals("1")) {
                    return ChannelResult.success("充值成功");
                }
                if (status.equals("2")||status.equals("3")) {
                    return ChannelResult.FAILED(msg);
                }
            }
            return ChannelResult.error(msg);
        }catch (Exception e) {
            e.printStackTrace();
            log.error("合合扫描王查询订单接口错误：",e);
            return  ChannelResult.error("合合扫描王查询订单接口错误");
        }
    }


    @Override
    public ChannelResult Notify(JSONObject apiConfig, Map<String, Object> data) {
        System.out.println("成功调用了Notify");
        return  ChannelResult.success("success");
    }


    public static String encryptByPublicKey(byte[] data, String publicKey) throws Exception {
        //解码公钥
        byte[] keyBytes = Base64.getDecoder().decode(publicKey);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);

        //数据加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        return Base64.getEncoder().encodeToString(cipher.doFinal(data));
    }

    public static String generateSign(Map<String, String> params,String appKey) throws Exception {
        // 使用TreeMap对参数按照ASCII码表顺序排序
        Map<String, String> sortedParams = new TreeMap<>(params);
        // 拼接参数串
        StringBuilder queryStringBuilder = new StringBuilder();
        for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
            queryStringBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
        }
        queryStringBuilder.append("secret=").append(appKey);
        return md5(queryStringBuilder.toString());
    }

    public static String md5(String signature) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(signature.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }



}
